﻿#region Usings

using GateShift.Client.Graphics.Interfaces;
using GateShift.Client.Graphics.Interfaces.Managers;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

#endregion

namespace GateShift.Client.Graphics.BaseClasses
{
    /// <summary>
    /// A screen is a grouping of related content. (such as a character selection screen, or login screen)
    /// </summary>
    public abstract class Screen : IScreen
    {
        protected float transparency = 0.0f;    // master transparency of the screen

        private const float transitionPeriod = 350.0f;
        private float transitionTimer = 0f;     // timer for fading screen in and out

        public IScreenManager Manager { get; protected set; }
        public bool IsOpening { get; private set; }
        public bool IsClosing { get; private set; }
        public bool IsFullyOpen { get; private set; }

        public Screen(IScreenManager screenManager)
        {
            this.Manager = screenManager;
        }

        public virtual void Initialize()
        {
        }

        public virtual void LoadContent()
        {
        }

        /// <summary>
        /// Updates the status of the screen (and its transparency) while it fades in or out
        /// </summary>
        public void Transition(GameTime time)
        {
            transitionTimer += (float)time.ElapsedGameTime.TotalMilliseconds;
            float percentTransitioned = MathHelper.Clamp(transitionTimer / transitionPeriod, 0.0f, 1.0f);

            // update the screen's overall transparency
            transparency = IsOpening ? percentTransitioned : 1 - percentTransitioned;

            // update the screen's components' transparencies
            OnTransparencyChange();

            // check if the transition is finished
            if (percentTransitioned == 1)
            {
                transitionTimer = 0f;
                if (IsOpening)
                {
                    IsFullyOpen = true;
                    ConnectControls();
                }
                else
                    IsFullyOpen = false;

                IsClosing = false;
                IsOpening = false;
            }
        }

        /// <summary>
        /// Tells the screen to start fading in
        /// </summary>
        public void StartOpening()
        {
            IsClosing = false;
            IsOpening = true;
        }

        /// <summary>
        /// Tells the screen to start fading out
        /// </summary>
        public void StartClosing()
        {
            IsFullyOpen = false;
            IsClosing = true;
            IsOpening = false;
            DisconnectControls();
        }

        /// <summary>
        /// Tells the screen to instantly open (no transition)
        /// </summary>
        public void OpenImmediately()
        {
            IsFullyOpen = true;
            IsClosing = false;
            IsOpening = false;
            ConnectControls();
        }

        /// <summary>
        /// Tells the screen to instantly close (no transition)
        /// </summary>
        public void CloseImmediately()
        {
            IsFullyOpen = false;
            IsClosing = false;
            IsOpening = false;
            DisconnectControls();
        }

        /// <summary>
        /// Called when the screen manager transitions the screen so the screen may properly update
        /// its controls' transparencies
        /// </summary>
        protected abstract void OnTransparencyChange();

        /// <summary>
        /// Connects the screen's controls to input devices
        /// </summary>
        public abstract void ConnectControls();

        /// <summary>
        /// Disconnects screen controls from input devices
        /// </summary>
        public abstract void DisconnectControls();

        /// <summary>
        /// Updates the screen's dynamic components
        /// </summary>
        public abstract void Update(GameTime time);

        /// <summary>
        /// Renders the screen
        /// </summary>
        public abstract void Draw(SpriteBatch sb);

    }
}